Java contiene un numero enorme de excepciones listas para usarse las cuales podrían ser muy útiles para casi todo tipo de situación que se pudiese presentar. Sin embargo, es posible definir nuestras propias excepciones en caso de se necesario para solventar nuestras necesidades particulares. En este post vamos a definir una nueva excepción de ejemplo para un caso en concreto. Para definir una excepción tenemos que crear una clase que herede de Exception, la cual ya contiene muchos métodos definidos que funcionan perfectamente, ya dependerá de nosotros si queremos sobrescribir alguno de esos métodos. En mi tiempo de experiencia desarrollando en Java, han sido muy pocas las veces la necesidad de sobrescribir algún método con los que ya viene por defecto Exception que no sea alguno de sus constructores.
Para este ejemplo definiremos un método muy sencillo que regresa un String con un mensaje indicando si una calificación de un alumno es aprobatoria o no. Para efectos del ejemplo se considerara que la calificación puede ser de 0 a 100, en donde 70 a 100 es aprobatorio y 0 a 69 es reprobatoria. Cualquier otro número fuera de ese rango como -1 ó 101 seria inválido y debería provocar una excepción.
import java.util.Objects;
public class NewClass {
public static void main(String[] args) {
try{
System.out.println(mensajeDeCalificacion(50));
} catch(CalificacionNoValidaException ex) {
System.out.println("Ocurrió un error: "+ex);
}
}
public static String mensajeDeCalificacion(Integer calificacion) throws CalificacionNoValidaException {
if(Objects.isNull(calificacion))
throw new NullPointerException("calificacion es null");
if(calificacion < 0 || calificacion > 100)
throw new CalificacionNoValidaException(calificacion);
return calificacion < 70 ? "Reprobaste, burro!" : "Aprobaste, felicidades";
}
}
class CalificacionNoValidaException extends Exception {
public CalificacionNoValidaException(Integer calificacion) {
super("Calificación inválida: "+calificacion);
}
}
En el ejemplo anterior definimos un nuevo tipo de excepción nueva en la linea 24 creando una clase que herede de Exception. Después creamos un método llamado mensajeDeCalificacion el cual regresará un String indicando si se aprobó o reprobó en base al parámetro calificacion que recibe. Antes de revisar si la calificación es aprobatoria o no, el método mensajeDeCalificacion hace dos validaciones, primero valida si la calificación recibida es nula, si es así lanza un NullPointerException, si no, continua. Después valida si la calificación es válida, osea que no sea menor a 0 o mayor a 100, en caso de ser inválida lanza un CalificacionNoValidaException que es el nuevo tipo de Exception que acabamos de definir, y en caso de no ocurrir la excepción se regresa el String con el mensaje según sea el caso. Debido a que CalificacionNoValidaException hereda de Exception directamente, esta se convierte en una checked exception (las que repasamos en el post anterior), por lo que es necesario tratarla si no no compilará, es por eso que en la definición del método mensajeDeCalificacion hay un throws CalificacionNoValidaException el cual indica que dicho método puede lanzar una excepción de ese tipo y deberá ser tratada por quien use dicho método, que en este caso es dentro del método main en donde se deberá tratar esa excepción. ¿Y porque no es necesario hacer lo mismo con NullPointerException que también es explícitamente lanzado dentro del método mensajeDeCalificacion? La respuesta a eso es que NullPointerException es una unchecked exception porque dicha excepción hereda de RuntimeException, asi que no es necesario tratarla para que nuestro código compile. Si ejecutamos el código obtendremo lo siguiente:
run:
Reprobaste, burro!
BUILD SUCCESSFUL (total time: 0 seconds)
Debido a que estamos mandando un 50 como parámetro, el resultado es una calificación reprobatoria. Ahora si modificamos la linea 6 para mandarle un -5 en vez de 50, el flujo del código entrará dentro del catch del método main debido a que ocurre un CalificacionNoValidaException resultando en lo siguiente:
run:
Ocurrió un error: CalificacionNoValidaException: Calificación inválida: -5
BUILD SUCCESSFUL (total time: 0 seconds)
Ahora si mandamos un valor null ocurre lo siguiente:
run:
Exception in thread "main" java.lang.NullPointerException: calificacion es null
at NewClass.mensajeDeCalificacion(NewClass.java:15)
at NewClass.main(NewClass.java:6)
Como se puede ver, nuestro programa no entra a nuestro catch, de hecho el programa truena porque no estamos tratando las NullPointerException, para ello tendriamos que agregar otro catch que maneje ese tipo de exception.